package models

import (
	"codeless/utils"
	"os"
	"strings"
)

type CrudEngine struct {
	Name    string
	Process string
	Node    string
}
type UIEngine struct {
	Name    string
	Process string
}

func NewCrudEngine(code string) CrudEngine {
	codeList := strings.Split(code, ".")
	if len(codeList) >= 3 {
		return CrudEngine{
			Name:    codeList[0],
			Process: strings.ToLower(codeList[1]),
			Node:    codeList[2],
		}
	} else {
		return CrudEngine{
			Name:    "",
			Process: "",
			Node:    "",
		}
	}

}
func NewUIEngine(code string) UIEngine {
	codeList := strings.Split(code, ".")
	if len(codeList) >= 2 {
		return UIEngine{
			Name:    codeList[0] + ".ui",
			Process: strings.ToLower(codeList[1]),
		}
	} else {
		return UIEngine{
			Name:    "",
			Process: "",
		}
	}

}

type CrudInfo struct {
	Mod    ModInfo               `json:"mod"`
	List   map[string]CrudList   `json:"list"`
	Page   map[string]CrudPage   `json:"page"`
	Get    map[string]CrudGet    `json:"get"`
	Add    map[string]CrudAdd    `json:"add"`
	Update map[string]CrudUpdate `json:"update"`
	Del    map[string]CrudDel    `json:"del"`
}
type CrudSql struct {
	Sql map[string]string `json:"sql"`
}

func (c *CrudInfo) checkDisable() {
	for k, v := range c.Update {
		v.checkDisable()
		c.Update[k] = v
	}

	for k, v := range c.Del {
		v.checkDisable()
		c.Del[k] = v
	}
	for k, v := range c.Add {
		v.checkDisable()
		c.Add[k] = v
	}
	for k, v := range c.List {
		v.checkDisable()
		c.List[k] = v
	}
	for k, v := range c.Page {
		v.checkDisable()
		c.Page[k] = v
	}
	for k, v := range c.Get {
		v.checkDisable()
		c.Get[k] = v
	}
}

var ResourcePath = "resource/crud/"

func LoadCrudFile(name string, cache bool) (*CrudInfo, bool) {
	filePath := ResourcePath + name + ".json"
	if !utils.PathExists(filePath) {
		return &CrudInfo{}, false
	}
	if cache {
		if x, found := utils.GetCache(name); found {
			return x.(*CrudInfo), true
		}
	}

	data, err := os.ReadFile(filePath)
	if err != nil {
		return &CrudInfo{}, false
	}
	jsonData := string(data)
	var crudSql CrudSql
	utils.Unmarshal(data, &crudSql)
	if len(crudSql.Sql) >= 1 {
		for k, v := range crudSql.Sql {
			refId := "@{" + k + "}"
			jsonData = strings.ReplaceAll(jsonData, refId, v)
		}
		info := LoadCrudByte([]byte(jsonData))
		if cache {
			utils.SetCache(name, info)
		}
		return info, true
	}
	info := LoadCrudByte(data)
	if cache {
		utils.SetCache(name, info)
	}
	return info, true

}
func LoadCrudByte(jsonByte []byte) *CrudInfo {
	var info CrudInfo
	uerr := utils.Unmarshal(jsonByte, &info)
	if uerr == nil {
		info.checkDisable()
	}
	return &info
}

func LoadUIFile(name string, cache bool) (UI, bool) {
	filePath := ResourcePath + name + ".json"
	if !utils.PathExists(filePath) {
		return UI{}, false
	}
	if cache {
		if x, found := utils.GetCache(name); found {
			return x.(UI), true
		}
	}

	data, err := os.ReadFile(filePath)
	if err != nil {
		return UI{}, false
	}
	info := LoadUIByte(data)
	if cache {
		utils.SetCache(name, info)
	}
	return info, true
}
func LoadUIByte(jsonByte []byte) UI {
	var info UI
	utils.Unmarshal(jsonByte, &info)
	return info
}
